package br.ufcg.edu.descompressao;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.List;

import br.ufcg.edu.algoritimo.DecodificadorHuffman;
import br.ufcg.edu.algoritimo.Huffman;
import br.ufcg.edu.algoritimo.No;
import br.ufcg.edu.util.Constantes;

public class Descompressao implements DescompressaoIF {
	
	private InputStream inputStream;
	private OutputStream outputStream;
	
	public Descompressao(InputStream inputStream, OutputStream outputStream) {
		this.inputStream = inputStream;
		this.outputStream = outputStream;
	}

	@Override
	public void start() throws IOException {
		DataInputStream reader = null;
		try{
		reader = new DataInputStream(new BufferedInputStream(
				this.inputStream));
		int numeroDeCaracteres = (int) reader.readChar();
		int totalCaracteres = 0;
		List<No> nos = new ArrayList<No>();
		for (int i = 0; i < numeroDeCaracteres; i++) {
			char caracter = (char) reader.readChar();
			int ocorrencia = reader.readInt();
			totalCaracteres += ocorrencia;
			nos.add(new No(null, null, ocorrencia, caracter, true));
		}

		Huffman huffman = new Huffman();
		No no = huffman.construirArvore(nos);
		lerBits(reader, no, totalCaracteres);
		}finally{
			reader.close();			
		}
	}

	private void lerBits(DataInputStream reader, No no, int totalCaracteres)
			throws IOException {
		DecodificadorHuffman decodificador = new DecodificadorHuffman(no, totalCaracteres);
		DataOutputStream writer = geraArquivoSaida();

		while (reader.available() > 1) {
			int valorSequencia = reader.readChar();
			String sequencia = preencherEspacoSequencia(
					Integer.toString(valorSequencia, 2));
			salvaEmArquivo(writer,
					decodificador.decodificaCaracteres(sequencia.toCharArray()));
		}
		
		if(reader.available() > 0){
			writer.write(reader.read());
		}
		writer.close();

	}

	private void salvaEmArquivo(DataOutputStream writer,
			String decodificaCaracteres) throws IOException {
		writer.writeChars(decodificaCaracteres);
	}

	private DataOutputStream geraArquivoSaida() throws IOException {
		DataOutputStream writer = new DataOutputStream(
				new BufferedOutputStream(this.outputStream));
		return writer;
	}

	private String preencherEspacoSequencia(String sequencia) {
		StringBuilder saida = new StringBuilder();
		int valorCompletar = Constantes.NUMERO_DE_BITS_DE_CARACTER
				- sequencia.length();
		for (int i = 0; i < valorCompletar; i++) {
			saida.append(Constantes.BIT_ZERO);
		}
		saida.append(sequencia);

		return saida.toString();

	}

	public static void main(String[] args) throws IOException {
		Descompressao desc = new Descompressao(System.in, System.out);
		desc.start();
	}

}
